# backend/api/v1/wireguard.py
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import Response
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List

from backend.core.wireguard import WireGuardManager
from backend.database import get_db
from backend.crud import user_subscription as us_crud
from backend.crud import node as node_crud
from backend.schemas.wireguard import ClientConfigResponse

router = APIRouter(prefix="/wireguard", tags=["wireguard"])
wg_manager = WireGuardManager()


@router.get("/config/{user_subscription_id}", response_model=ClientConfigResponse)
async def get_client_config(
        user_subscription_id: str,
        db: AsyncSession = Depends(get_db)
):
    """
    为用户订阅生成WireGuard配置文件
    """
    try:
        # 获取用户订阅信息
        user_subs = await us_crud.get_user_subscriptions_by_id(db, user_subscription_id)
        if not user_subs:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户订阅不存在"
            )

        user_sub = user_subs[0]  # 取第一个订阅

        # 检查订阅是否有效
        if not user_sub.is_active:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="订阅未激活"
            )

        # 获取节点信息
        node = await node_crud.get_node(db, user_sub.node_id)
        if not node:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="节点不存在"
            )

        # 如果还没有WireGuard密钥对，生成并保存
        if not user_sub.wg_private_key or not user_sub.wg_public_key:
            keypair = wg_manager.generate_keypair()

            # 分配IP地址（这里需要获取已使用的IP列表）
            used_ips = await us_crud.get_used_ips(db, user_sub.node_id)
            client_ip = wg_manager.allocate_client_ip(node.subnet, used_ips)

            # 更新用户订阅的WireGuard信息
            await us_crud.update_wireguard_info(
                db,
                user_subscription_id,
                keypair["private_key"],
                keypair["public_key"],
                client_ip
            )

            user_sub.wg_private_key = keypair["private_key"]
            user_sub.wg_public_key = keypair["public_key"]
            user_sub.client_ip = client_ip

        # 生成配置文件
        config_content = wg_manager.generate_client_config(
            client_private_key=user_sub.wg_private_key,
            server_public_key=node.wg_public_key,
            server_endpoint=f"{node.host}:{node.wg_port}",
            client_ip=user_sub.client_ip,
            dns_servers=node.get_dns_servers_list()
        )

        filename = f"wg-{user_sub.user_id}-{node.name}.conf"

        return ClientConfigResponse(
            config_content=config_content,
            filename=filename,
            client_ip=user_sub.client_ip
        )

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"生成配置文件失败: {str(e)}"
        )


# backend/api/v1/wireguard.py - 修复编码问题
@router.get("/config/{user_subscription_id}/download")
async def download_client_config(
        user_subscription_id: str,
        db: AsyncSession = Depends(get_db)
):
    """
    下载WireGuard配置文件
    """
    try:
        # 直接复制get_client_config的逻辑，避免循环调用
        user_subs = await us_crud.get_user_subscriptions_by_id(db, user_subscription_id)
        if not user_subs:
            raise HTTPException(status_code=404, detail="用户订阅不存在")

        user_sub = user_subs[0]

        if not user_sub.is_active:
            raise HTTPException(status_code=400, detail="订阅未激活")

        node = await node_crud.get_node(db, user_sub.node_id)
        if not node:
            raise HTTPException(status_code=404, detail="节点不存在")

        # 如果还没有WireGuard密钥对，生成并保存
        if not user_sub.wg_private_key or not user_sub.wg_public_key:
            keypair = wg_manager.generate_keypair()
            used_ips = await us_crud.get_used_ips(db, user_sub.node_id)
            client_ip = wg_manager.allocate_client_ip(node.subnet, used_ips)
            await us_crud.update_wireguard_info(
                db,
                user_subscription_id,
                keypair["private_key"],
                keypair["public_key"],
                client_ip
            )
            # 重新获取更新后的数据
            user_subs = await us_crud.get_user_subscriptions_by_id(db, user_subscription_id)
            user_sub = user_subs[0]

        # 生成配置文件
        config_content = wg_manager.generate_client_config(
            client_private_key=user_sub.wg_private_key,
            server_public_key=node.wg_public_key,
            server_endpoint=f"{node.host}:{node.wg_port}",
            client_ip=user_sub.client_ip,
            dns_servers=node.get_dns_servers_list()
        )

        # 修复：使用英文文件名避免编码问题
        filename = f"wg-config-{user_subscription_id[:8]}.conf"

        # 使用Response并指定utf-8编码
        return Response(
            content=config_content,
            media_type="text/plain; charset=utf-8",
            headers={
                "Content-Disposition": f"attachment; filename={filename}"
            }
        )

    except HTTPException:
        raise
    except Exception as e:
        # 添加详细错误日志
        import traceback
        print(f"❌ 下载配置文件错误: {str(e)}")
        print(f"🔍 错误详情: {traceback.format_exc()}")
        raise HTTPException(
            status_code=500,
            detail=f"下载配置文件失败: {str(e)}"
        )


@router.post("/nodes/{node_id}/setup")
async def setup_wireguard_node(
        node_id: str,
        db: AsyncSession = Depends(get_db)
):
    """
    为节点设置WireGuard
    """
    try:
        node = await node_crud.get_node(db, node_id)
        if not node:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="节点不存在"
            )

        # 生成服务器密钥对
        keypair = wg_manager.generate_keypair()

        # 更新节点信息
        await node_crud.update_wireguard_info(
            db,
            node_id,
            keypair["private_key"],
            keypair["public_key"],
            f"{node.host}:{node.wg_port}"
        )

        return {
            "message": "WireGuard配置完成",
            "public_key": keypair["public_key"],
            "endpoint": f"{node.host}:{node.wg_port}"
        }

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"设置WireGuard失败: {str(e)}"
        )